package com.rui.responsibility.main;

import com.rui.responsibility.model.AuthHandler;
import com.rui.responsibility.model.Handler;
import com.rui.responsibility.model.LoginHandler;
import com.rui.responsibility.model.ValidateHandler;
import com.rui.responsibility.model.base.BaseAuthHandler;
import com.rui.responsibility.model.base.BaseHandler;
import com.rui.responsibility.model.base.BaseLoginHandler;
import com.rui.responsibility.model.base.BaseValidateHandler;
import com.rui.responsibility.obj.User;

/**
 * 职责链模式（chain of responsibility pattern）
 * <p>
 * <p>
 * 职责链模式是将链中每一个节点看作是一个对象，每个节点处理的请求均不同，且内部自动维护一个下一节点对象。当一个请求从链式的首端发出时，会沿着链的路径依次传递给每一个节点对象，直至有对象处理这个请求为止。
 * <p>
 * 职责链模式主要包含以下角色：
 * 抽象处理者（Handler）角色：定义一个处理请求的接口，包含抽象处理方法和一个后继连接。
 * 具体处理者（Concrete Handler）角色：实现抽象处理者的处理方法，判断能否处理本次请求，如果可以处理请求则处理，否则将该请求转给它的后继者。
 * 客户类（Client）角色：创建处理链，并向链头的具体处理者对象提交请求，它不关心处理细节和请求的传递过程。
 * <p>
 * 适用场景：
 * 多个对象可以处理同一请求，但具体由哪个对象处理则在运行时动态决定。
 * 在不明确指定接收者的情况下，向多个对象中的一个提交一个请求。
 * 可动态指定一组对象处理请求。
 * <p>
 * 优点：
 * 将请求与处理解耦。
 * 请求处理者（节点对象）只需关注自己感兴趣的请求进行处理即可，对于不感兴趣的请求，直接转发给下一级节点对象。
 * 具备链式传递处理请求功能，请求发送者无需知晓链路结构，只需等待请求处理结果。
 * 链路结构灵活，可以通过改变链路结构动态地新增或删减责任。
 * 易于扩展新的请求处理类（节点），符合开闭原则。
 * <p>
 * 缺点：
 * 责任链太长或者处理时间过长，会影响整体性能。
 * 如果节点对象存在循环引用时，会造成死循环，导致系统崩溃。
 *
 * @author ZhangRui
 * @date 2023/03/03 14:31
 **/
public class Main {

    public static void main(String[] args) {
        User user = new User();
        //校验通过
        //用户名或者密码不正确!请检查!
        user.setUsername("pyy52hz");
        user.setPassword("1234567");
        baseLogin(user);


        //校验通过
        //登陆成功!角色为管理员!
        //角色为管理员,可以进行下一步操作!
        user.setUsername("pyy52hz");
        user.setPassword("123456");
        baseLogin(user);


        login(user);

    }


    public static void baseLogin(User user) {

        BaseHandler validateBaseHandler = new BaseValidateHandler();
        BaseHandler loginBaseHandler = new BaseLoginHandler();
        BaseHandler authBaseHandler = new BaseAuthHandler();

        validateBaseHandler.next(loginBaseHandler);
        loginBaseHandler.next(authBaseHandler);

        validateBaseHandler.doHandler(user);
    }

    public static void login(User user) {
        Handler.Builder builder = new Handler.Builder();
        builder.addHandler(new ValidateHandler())
                .addHandler(new LoginHandler())
                .addHandler(new AuthHandler());
        builder.build().doHandler(user);
    }

}
